package org.hawk.gwt.ppc.parser.impl;

import java.io.InputStream;

import junit.framework.TestCase;

import org.hawk.gwt.ppc.parser.ClassDescriptor;
import org.hawk.gwt.ppc.parser.ClassDescriptor.ClassDescriptorType;
import org.hawk.gwt.ppc.parser.JavaKeywords;
import org.hawk.gwt.ppc.parser.JavaParser;
import org.hawk.gwt.ppc.parser.impl.mock.AnnotationMock1;
import org.hawk.gwt.ppc.parser.impl.mock.ClassMock1;
import org.hawk.gwt.ppc.parser.impl.mock.EnumMock;
import org.hawk.gwt.ppc.parser.impl.mock.InterfaceMock;
import org.hawk.gwt.ppc.utils.Name;
import org.hawk.gwt.ppc.utils.PreprocessorException;

public class ClassDescriptorTestCase extends TestCase {

	public void testPublicClass() throws PreprocessorException {
		ClassDescriptor clazz = getClass(ClassMock1.class.getName());
		assertNotNull(clazz);
		
		assertEquals(ClassMock1.class.getSimpleName(), clazz.getName());
		assertEquals(ClassDescriptorType.CLASS, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(1, clazz.getExtendsSection().size());
		assertEquals(2, clazz.getImplementsSection().size());
		assertEquals(2, clazz.getMethods().size());
		assertEquals(2, clazz.getFields().size());
		assertEquals(2, clazz.getInitializers().size());
		assertEquals(2, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(1, clazz.getModifiers().size());
		assertEquals(JavaKeywords.PUBLIC, clazz.getModifiers().get(0));
	}
	
	public void testDefaultClass() throws PreprocessorException {
		String className = "org.hawk.gwt.ppc.parser.impl.mock.ClassMock2";
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("ClassMock2", clazz.getName());
		assertEquals(ClassDescriptorType.CLASS, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(0, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(0, clazz.getModifiers().size());
	}
	
	public void testEnum() throws PreprocessorException {
		String className = EnumMock.class.getName();
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("EnumMock", clazz.getName());
		assertEquals(ClassDescriptorType.ENUM, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(0, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(1, clazz.getModifiers().size());
		assertEquals(JavaKeywords.PUBLIC, clazz.getModifiers().get(0));
	}
	
	public void testInterface() throws PreprocessorException {
		String className = InterfaceMock.class.getName();
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("InterfaceMock", clazz.getName());
		assertEquals(ClassDescriptorType.INTERFACE, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(2, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(1, clazz.getModifiers().size());
		assertEquals(JavaKeywords.PUBLIC, clazz.getModifiers().get(0));
	}
	
	public void testAnnotation() throws PreprocessorException {
		String className = AnnotationMock1.class.getName();
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("AnnotationMock1", clazz.getName());
		assertEquals(ClassDescriptorType.ANNOTATION, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(2, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(1, clazz.getModifiers().size());
		assertEquals(JavaKeywords.PUBLIC, clazz.getModifiers().get(0));
	}
	
	public void testDefaultAnnotation() throws PreprocessorException {
		String className = "org.hawk.gwt.ppc.parser.impl.mock.AnnotationMock2";
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("AnnotationMock2", clazz.getName());
		assertEquals(ClassDescriptorType.ANNOTATION, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(2, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(0, clazz.getModifiers().size());
	}
	
	public void testAnnotatedClass() throws PreprocessorException {
		String className = "org.hawk.gwt.ppc.parser.impl.mock.AnnotatedClassMock";
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("AnnotatedClassMock", clazz.getName());
		assertEquals(ClassDescriptorType.CLASS, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(0, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(0, clazz.getModifiers().size());
	}
	
	public void testAnnotatedAnotation() throws PreprocessorException {
		String className = "org.hawk.gwt.ppc.parser.impl.mock.AnnotatedAnnotationMock";
		ClassDescriptor clazz = getClass(className);
		assertNotNull(clazz);
		
		assertEquals("AnnotatedAnnotationMock", clazz.getName());
		assertEquals(ClassDescriptorType.ANNOTATION, clazz.getType());
		assertEquals("", clazz.getTypeParameters());
		assertEquals(0, clazz.getExtendsSection().size());
		assertEquals(0, clazz.getImplementsSection().size());
		assertEquals(0, clazz.getMethods().size());
		assertEquals(0, clazz.getFields().size());
		assertEquals(0, clazz.getInitializers().size());
		assertEquals(0, clazz.getConstructors().size());
		assertEquals(0, clazz.getDeclaredClasses().size());
		assertEquals(0, clazz.getModifiers().size());
	}
	
	public void testHeavilyCommentedClass() throws PreprocessorException {
		//TODO: fail("Not implemented");
	}
	
	private ClassDescriptor getClass(String name) throws PreprocessorException {
		InputStream cu = getClass().getClassLoader().getResourceAsStream(Name.javaToFs(name));
		try {
			JavaParser parser = JavaParser.create(cu);
			return parser.parse().getTopClasses().get(0);
		} finally {
			try {
				cu.close();
			} catch(Exception ex) {
			}
		}
	}
}
